home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / util / gnu / oleo_src.lha / src / cells.c < prev    next >
C/C++ Source or Header  |  1992-08-18  |  10KB  |  482 lines

  1. /*    Copyright (C) 1990 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 1, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #define obstack_chunk_alloc ck_malloc
  20. #define obstack_chunk_free free
  21. #include "obstack.h"
  22. #include "funcdef.h"
  23. #include "sysdef.h"
  24.  
  25. #include "global.h"
  26. #include "cell.h"
  27. #include "eval.h"
  28. #include "errors.h"
  29.  
  30. struct value {
  31.     int    type;
  32.     union vals x;
  33. };
  34.  
  35. #define Float    x.c_d
  36. #define String    x.c_s
  37. #define Int    x.c_l
  38. #define Value    x.c_i
  39. #define Rng    x.c_r
  40.  
  41. #define ERROR(x)    \
  42.  {            \
  43.     p->Value=x;    \
  44.     p->type=TYP_ERR;\
  45.     return;        \
  46.  }
  47.  
  48.  
  49. static int
  50. cell FUN4(long,row, long,col, char *,dowhat, struct value *,p)
  51. {
  52.     struct func {
  53.         char *name;
  54.         int typ;
  55.     };
  56.  
  57.     static struct func cell_funs[] = {
  58.         { "row",    TYP_INT    },
  59.         { "column",    TYP_INT },
  60.         { "width",    TYP_INT },
  61.         { "lock",    TYP_STR },
  62.         { "protection",    TYP_STR },
  63.         { "justify",    TYP_STR },
  64.         { "alignment",    TYP_STR },
  65.         { "fmt",    TYP_STR },
  66.         { "format",    TYP_STR },
  67.         { "type",    TYP_STR },
  68.         { "formula",    TYP_STR },
  69.         { "value",    0    },
  70.         {0,        0    }
  71.     };
  72.  
  73.     CELL *cell_ptr;
  74.     char *strptr;
  75.     struct func *func;
  76.     struct func *f1;
  77.     int n;
  78.     extern default_lock;
  79.  
  80.     n=strlen(dowhat)-1;
  81.     f1=0;
  82.     for(func=cell_funs;func->name;func++)
  83.         if(   func->name[0]==dowhat[0]
  84.             && (n==0 || !strincmp(&(func->name[1]),&dowhat[1],n))) {
  85.             if(f1)
  86.                 return BAD_INPUT;
  87.             f1=func;
  88.         }
  89.     if(!f1)
  90.         return BAD_INPUT;
  91.     p->type=f1->typ;
  92.     switch(f1-cell_funs) {
  93.     case 0:
  94.         p->Int=row;
  95.         break;
  96.     case 1:
  97.         p->Int=col;
  98.         break;
  99.     case 2:
  100.         p->Int=get_width(col);
  101.         break;
  102.     case 3:
  103.     case 4:
  104.         p->String=((cell_ptr=find_cell(row,col)) ? GET_LCK(cell_ptr) : default_lock) ? "locked" : "unlocked";
  105.         break;
  106.     case 5:
  107.     case 6:
  108.         p->String=jst_to_str((cell_ptr=find_cell(row,col)) ? GET_JST(cell_ptr) : 0);
  109.         break;
  110.     case 7:
  111.     case 8:
  112.         p->String=fmt_to_str((cell_ptr=find_cell(row,col)) ? GET_FMT(cell_ptr) : 0);
  113.         break;
  114.     case 9:
  115.         cell_ptr=find_cell(row,col);
  116.         if(cell_ptr)
  117.             switch(GET_TYP(cell_ptr)) {
  118.              case TYP_FLT:
  119.                 p->String="float";
  120.                 break;
  121.             case TYP_INT:
  122.                 p->String="integer";
  123.                 break;
  124.             case TYP_STR:
  125.                 p->String="string";
  126.                 break;
  127.             case TYP_BOL:
  128.                 p->String="boolean";
  129.                 break;
  130.             case TYP_ERR:
  131.                 p->String="error";
  132.                 break;
  133.             default:
  134.                 p->String="Unknown";
  135.             }
  136.         else
  137.             p->String="null";
  138.         break;
  139.     case 10:
  140.         cell_ptr=find_cell(row,col);
  141.         if(cell_ptr && (GET_TYP(cell_ptr) || cell_ptr->cell_formula)) {
  142.             strptr=decomp(row,col,cell_ptr);
  143.             p->String=obstack_alloc(&tmp_mem,strlen(strptr)+1);
  144.             strcpy(p->String,strptr);
  145.             decomp_free();
  146.         } else
  147.             p->String="";
  148.         break;
  149.     case 11:
  150.         cell_ptr=find_cell(row,col);
  151.         if(cell_ptr) {
  152.             p->type=GET_TYP(cell_ptr);
  153.             p->x=cell_ptr->c_z;
  154.         } else
  155.             p->type=0;
  156.         break;
  157.     default:
  158.         return BAD_INPUT;
  159.     }
  160.     return 0;
  161. }
  162.  
  163.  
  164. static void
  165. do_curcell FUN1(struct value *,p)
  166. {
  167.     extern CELLREF curow,cucol;
  168.     int tmp;
  169.  
  170.     tmp=cell(curow,cucol,p->String,p);
  171.     if(tmp)
  172.         ERROR(tmp);
  173. }
  174.  
  175. static void
  176. do_my FUN1(struct value *,p)
  177. {
  178.     int tmp;
  179.  
  180.     tmp=cell(cur_row,cur_col,p->String,p);
  181.     if(tmp)
  182.         ERROR(tmp);
  183. }
  184.  
  185. /* Note that the second argument may be *anything* including ERROR.  If it is
  186.    error, we find the first occurence of that ERROR in the range */
  187.  
  188. static void
  189. do_member FUN1(struct value *,p)
  190. {
  191.     CELLREF crow;
  192.     CELLREF ccol;
  193.     int foundit;
  194.     CELL *cell_ptr;
  195.     struct rng *rptr;
  196.  
  197.     rptr= &(p->Rng);
  198.     find_cells_in_range(&(p->Rng));
  199.     while(cell_ptr=next_row_col_in_range(&crow,&ccol)) {
  200.         if(GET_TYP(cell_ptr)!=(p+1)->type)
  201.             continue;
  202.         switch((p+1)->type) {
  203.         case 0:
  204.             foundit=1;
  205.             break;
  206.         case TYP_FLT:
  207.             foundit=cell_ptr->cell_flt==(p+1)->Float;
  208.             break;
  209.         case TYP_INT:
  210.             foundit=cell_ptr->cell_int==(p+1)->Int;
  211.             break;
  212.         case TYP_STR:
  213.             foundit= !strcmp(cell_ptr->cell_str,(p+1)->String);
  214.             break;
  215.         case TYP_BOL:
  216.             foundit=cell_ptr->cell_bol==(p+1)->Value;
  217.             break;
  218.         case TYP_ERR:
  219.             foundit=cell_ptr->cell_err==(p+1)->Value;
  220.             break;
  221. #ifdef TEST
  222.         default:
  223.             panic("Unknown type (%d) in member",(p+1)->type);
  224.             foundit=0;
  225. #endif
  226.         }
  227.         if(foundit) {
  228.             no_more_cells();
  229.             p->Int = 1 + crow-p->Rng.lr + (ccol-p->Rng.lc)*(1+p->Rng.hr-p->Rng.lr);
  230.             p->type=TYP_INT;
  231.             return;
  232.         }
  233.     }
  234.     p->Int=0L;
  235.     p->type=TYP_INT;
  236. }
  237.  
  238. static void
  239. do_smember FUN1(struct value *,p)
  240. {
  241.     CELLREF crow;
  242.     CELLREF ccol;
  243.     CELL *cell_ptr;
  244.     char *string;
  245.  
  246.     string=(p+1)->String;
  247.     find_cells_in_range(&(p->Rng));
  248.     while(cell_ptr=next_row_col_in_range(&crow,&ccol)) {
  249.         if(   (GET_TYP(cell_ptr)==0 && string[0]=='\0')
  250.            || (cell_ptr && GET_TYP(cell_ptr)==TYP_STR && strstr(string,cell_ptr->cell_str))) {
  251.             no_more_cells();
  252.             p->Int = 1 + (crow-p->Rng.lr)
  253.                   + (ccol-p->Rng.lc)*(1+(p->Rng.hr-p->Rng.lr));
  254.             p->type=TYP_INT;
  255.             return;
  256.         }
  257.     }
  258.     p->Int = 0L;
  259.     p->type=TYP_INT;
  260. }
  261.  
  262. static void
  263. do_members FUN1(struct value *,p)
  264. {
  265.     CELLREF crow;
  266.     CELLREF ccol;
  267.     CELL *cell_ptr;
  268.     char *string;
  269.  
  270.     string=(p+1)->String;
  271.     find_cells_in_range(&(p->Rng));
  272.     while(cell_ptr=next_row_col_in_range(&crow,&ccol)) {
  273.         if(GET_TYP(cell_ptr)!=TYP_STR)
  274.             continue;
  275.         if(strstr(cell_ptr->cell_str,string)) {
  276.             no_more_cells();
  277.             p->Int = 1 + (crow-p->Rng.lr)
  278.                  + (ccol-p->Rng.lc)*(1+(p->Rng.hr-p->Rng.lr));
  279.             p->type=TYP_INT;
  280.             return;
  281.         }
  282.     }
  283.     p->Int = 0L;
  284.     p->type=TYP_INT;
  285. }
  286.  
  287. static void
  288. do_pmember FUN1(struct value *,p)
  289. {
  290.     CELLREF crow;
  291.     CELLREF ccol;
  292.     CELL *cell_ptr;
  293.     char *string;
  294.  
  295.     string=(p+1)->String;
  296.     find_cells_in_range(&(p->Rng));
  297.     while(cell_ptr=next_row_col_in_range(&crow,&ccol)) {
  298.         if(   (GET_TYP(cell_ptr)==0 && string[0]=='\0')
  299.            || (cell_ptr && GET_TYP(cell_ptr)==TYP_STR && !strncmp(string,cell_ptr->cell_str,strlen(cell_ptr->cell_str)))) {
  300.             no_more_cells();
  301.             p->Int = 1 + (crow-p->Rng.lr)
  302.                   + (ccol-p->Rng.lc)*(1+(p->Rng.hr-p->Rng.lr));
  303.             p->type=TYP_INT;
  304.             return;
  305.         }
  306.     }
  307.     p->Int = 0L;
  308.     p->type=TYP_INT;
  309. }
  310.  
  311. static void
  312. do_memberp FUN1(struct value *,p)
  313. {
  314.     CELLREF crow;
  315.     CELLREF ccol;
  316.     CELL *cell_ptr;
  317.     int tmp;
  318.     char *string;
  319.  
  320.     string=(p+1)->String;
  321.     find_cells_in_range(&(p->Rng));
  322.     tmp=strlen(string);
  323.     while(cell_ptr=next_row_col_in_range(&crow,&ccol)) {
  324.         if(GET_TYP(cell_ptr)!=TYP_STR)
  325.             continue;
  326.         if(!strncmp(cell_ptr->cell_str,string,tmp)) {
  327.             no_more_cells();
  328.             p->Int = 1 + (crow-p->Rng.lr)
  329.                   + (ccol-p->Rng.lc)*(1+(p->Rng.hr-p->Rng.lr));
  330.             p->type=TYP_INT;
  331.             return;
  332.         }
  333.     }
  334.     p->Int = 0L;
  335.     p->type=TYP_INT;
  336. }
  337.  
  338. static void
  339. do_hlookup FUN1(struct value *,p)
  340. {
  341.  
  342.     struct rng *rng    = &((p  )->Rng);
  343.     double fltval    =   (p+1)->Float;
  344.     long offset    =   (p+2)->Int;
  345.  
  346.     CELL *cell_ptr;
  347.     double f;
  348.     CELLREF col;
  349.     CELLREF row;
  350.     char *strptr;
  351.  
  352.     row=rng->lr;
  353.     for(col=rng->lc;col<=rng->hc;col++) {
  354.         if(!(cell_ptr=find_cell(row,col)))
  355.             ERROR(NON_NUMBER);
  356.         switch(GET_TYP(cell_ptr)) {
  357.         case TYP_FLT:
  358.             if(fltval<cell_ptr->cell_flt)
  359.                 goto out;
  360.             break;
  361.         case TYP_INT:
  362.             if(fltval<cell_ptr->cell_int)
  363.                 goto out;
  364.             break;
  365.         case TYP_STR:
  366.             strptr=cell_ptr->cell_str;
  367.             f=astof(&strptr);
  368.             if(!*strptr && fltval>f)
  369.                 goto out;
  370.             else
  371.                 ERROR(NON_NUMBER);
  372.         case 0:
  373.         case TYP_BOL:
  374.         case TYP_ERR:
  375.         default:
  376.             ERROR(NON_NUMBER);
  377.         }
  378.     }
  379.  out:
  380.     if(col==rng->lc)
  381.         ERROR(OUT_OF_RANGE);
  382.     --col;
  383.     row=rng->lr+offset;
  384.     if(row>rng->hr)
  385.         ERROR(OUT_OF_RANGE);
  386.     cell_ptr=find_cell(row,col);
  387.     if(!cell_ptr) {
  388.         p->type=0;
  389.         p->Int=0;
  390.     } else {
  391.         p->type=GET_TYP(cell_ptr);
  392.         p->x=cell_ptr->c_z;
  393.     }
  394. }
  395.  
  396. static void
  397. do_vlookup FUN1(struct value *,p)
  398. {
  399.  
  400.     struct rng *rng    = &((p  )->Rng);
  401.     double fltval    =   (p+1)->Float;
  402.     long offset    =   (p+2)->Int;
  403.  
  404.     CELL *cell_ptr;
  405.     double f;
  406.     CELLREF col;
  407.     CELLREF row;
  408.     char *strptr;
  409.  
  410.     col=rng->lc;
  411.     for(row=rng->lr;row<=rng->hr;row++) {
  412.         if(!(cell_ptr=find_cell(row,col)))
  413.             ERROR(NON_NUMBER);
  414.         switch(GET_TYP(cell_ptr)) {
  415.         case TYP_FLT:
  416.             if(fltval<cell_ptr->cell_flt)
  417.                 goto out;
  418.             break;
  419.         case TYP_INT:
  420.             if(fltval<cell_ptr->cell_int)
  421.                 goto out;
  422.             break;
  423.         case TYP_STR:
  424.             strptr=cell_ptr->cell_str;
  425.             f=astof(&strptr);
  426.             if(!*strptr && fltval>f)
  427.                 goto out;
  428.             else
  429.                 ERROR(NON_NUMBER);
  430.         case 0:
  431.         case TYP_BOL:
  432.         case TYP_ERR:
  433.         default:
  434.             ERROR(NON_NUMBER);
  435.         }
  436.     }
  437.  out:
  438.     if(row==rng->lr)
  439.         ERROR(OUT_OF_RANGE);
  440.     --row;
  441.     col=rng->lc+offset;
  442.     if(col>rng->hc)
  443.         ERROR(OUT_OF_RANGE);
  444.  
  445.     cell_ptr=find_cell(row,col);
  446.     if(!cell_ptr) {
  447.         p->type=0;
  448.         p->Int=0;
  449.     } else {
  450.         p->type=GET_TYP(cell_ptr);
  451.         p->x=cell_ptr->c_z;
  452.     }
  453. }
  454.  
  455. static void
  456. do_cell FUN1(struct value *,p)
  457. {
  458.     int tmp;
  459.  
  460.     tmp=cell(p->Int,(p+1)->Int,(p+2)->String,p);
  461.     if(tmp)
  462.         ERROR(tmp);
  463. }
  464.  
  465. struct function cells_funs[] = {
  466. { C_FN1|C_T,      X_A1,        "S",    do_curcell,    "curcell" },
  467. { C_FN1|C_T,      X_A1,        "S",    do_my,    "my" },
  468. { C_FN3|C_T,      X_A3,        "IIS",  do_cell,    "cell" },
  469.  
  470. { C_FN2,      X_A2,        "RA",   do_member,    "member" },
  471. { C_FN2,      X_A2,        "RS",   do_smember,    "smember" },
  472. { C_FN2,      X_A2,        "RS",   do_members,    "members" },
  473. { C_FN2,      X_A2,        "RS",   do_pmember,    "pmember" },
  474. { C_FN2,      X_A2,        "RS",   do_memberp,    "memberp" },
  475.  
  476. { C_FN3,      X_A3,        "RFI",  do_hlookup,    "hlookup" },
  477. { C_FN3,      X_A3,        "RFI",  do_vlookup,    "vlookup" },
  478.  
  479. { 0,        0,        "",        0,         0 },
  480. };
  481.  
  482.